home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-11-20 | 37.2 KB | 1,484 lines |
- //------------------------------------------------------------------------
- //
- // Calculator.wfm -- Calculator
- //
- // This file contains a calculator form. This calculator
- // contains pushbuttons for numeric input and operations. It
- // also contains 2 entryfields -- the main display, showing the
- // current calculation, a hidden entry field for storing values
- // to memory. Keyboard input is handled through a paintbox control
- // that is not visible to the user.
- //
- // Dependencies: Calculator.ICO
- //
- // Visual dBASE Samples Group
- //
- // $Revision: 1.10 $
- //
- // Copyright (c) 1997, Borland International, Inc.
- // All rights reserved.
- //
- //------------------------------------------------------------------------
- //
-
-
- #define BASE_HEX 16
- #define BASE_DEC 10
- #define BASE_OCT 8
- #define BASE_BIN 2
-
- #define MAX_DIGITS_DEC 18
- #define MAX_DIGITS_OCT 16
- #define MAX_DIGITS_BIN 16
- #define MAX_DIGITS_HEX 8
- #define DISPLAY_LEN 18
- #define HEX_OVERFLOW 2^32
- #define DEC_OVERFLOW 10^18
- #define ALLTRIM(x) LTRIM(RTRIM(x))
-
- set talk off
- local f
- ** END HEADER -- do not remove this line
- //
- // Generated on 11/10/97
- //
- parameter bModal
- local f
- f = new CALCULATORFORM()
- if (bModal)
- f.mdi = false // ensure not MDI
- f.readModal()
- else
- f.open()
- endif
-
- class CALCULATORFORM of FORM
- with (this)
- onGotFocus = class::FORM_ONGOTFOCUS
- onClose = class::FORM_ONCLOSE
- open = class::FORM_OPEN
- scaleFontSize = 8
- scaleFontBold = false
- colorNormal = "BTNTEXT/BTNFACE"
- height = 13.0455
- left = 16
- top = 3
- width = 42.5714
- text = "Calculator"
- mdi = false
- sizeable = false
- mousePointer = 1 // Arrow
- maximize = false
- icon = "FILE Calculator.ico"
- endwith
-
-
- this.RECTANGLE1 = new RECTANGLE(this)
- with (this.RECTANGLE1)
- left = 1
- top = 2.3182
- width = 41
- height = 1.25
- metric = 0 // Chars
- text = ""
- colorNormal = "WindowText/BtnFace"
- fontSize = 8
- endwith
-
-
- this.KEYHANDLER = new PAINTBOX(this)
- with (this.KEYHANDLER)
- onChar = class::KEYHANDLER_ONCHAR
- colorNormal = "BtnFace/BtnFace"
- height = 0.5
- left = 0.1
- top = 0.5
- width = 0.1
- metric = 0 // Chars
- endwith
-
-
- this.MEMORY = new ENTRYFIELD(this)
- with (this.MEMORY)
- enabled = false
- height = 1
- left = 1
- top = 11.5
- width = 41
- metric = 0 // Chars
- function = "J"
- colorNormal = "BtnText/BtnFace"
- colorHighLight = ""
- fontSize = 8
- value = " "
- validRequired = true
- borderStyle = 7 // Client
- endwith
-
-
- this.B7 = new PUSHBUTTON(this)
- with (this.B7)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 1
- top = 4
- width = 6
- text = "7"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "B/BtnFace"
- value = false
- endwith
-
-
- this.B8 = new PUSHBUTTON(this)
- with (this.B8)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 8
- top = 4
- width = 6
- text = "8"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "B/BtnFace"
- value = false
- endwith
-
-
- this.B9 = new PUSHBUTTON(this)
- with (this.B9)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 15
- top = 4
- width = 6
- text = "9"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "B/BtnFace"
- value = false
- endwith
-
-
- this.B4 = new PUSHBUTTON(this)
- with (this.B4)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 1
- top = 5.5
- width = 6
- text = "4"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "B/BtnFace"
- value = false
- endwith
-
-
- this.B5 = new PUSHBUTTON(this)
- with (this.B5)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 8
- top = 5.5
- width = 6
- text = "5"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "B/BtnFace"
- value = false
- endwith
-
-
- this.B6 = new PUSHBUTTON(this)
- with (this.B6)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 15
- top = 5.5
- width = 6
- text = "6"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "B/BtnFace"
- value = false
- endwith
-
-
- this.B1 = new PUSHBUTTON(this)
- with (this.B1)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 1
- top = 7
- width = 6
- text = "1"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "B/BtnFace"
- value = false
- endwith
-
-
- this.B2 = new PUSHBUTTON(this)
- with (this.B2)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 8
- top = 7
- width = 6
- text = "2"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "B/BtnFace"
- value = false
- endwith
-
-
- this.B3 = new PUSHBUTTON(this)
- with (this.B3)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 15
- top = 7
- width = 6
- text = "3"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "B/BtnFace"
- value = false
- endwith
-
-
- this.OPPLUSMINUS = new PUSHBUTTON(this)
- with (this.OPPLUSMINUS)
- onClick = class::OPPLUSMINUS_ONCLICK
- height = 1
- left = 29
- top = 7
- width = 6
- text = "+/-"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "BtnText/BtnFace"
- value = false
- endwith
-
-
- this.B0 = new PUSHBUTTON(this)
- with (this.B0)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 1
- top = 8.5
- width = 6
- text = "0"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "B/BtnFace"
- value = false
- endwith
-
-
- this.PERIOD = new PUSHBUTTON(this)
- with (this.PERIOD)
- onClick = class::PERIOD_ONCLICK
- height = 1
- left = 8
- top = 8.5
- width = 6
- text = ". "
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "B/BtnFace"
- value = false
- endwith
-
-
- this.OPPOWER = new PUSHBUTTON(this)
- with (this.OPPOWER)
- onClick = class::OPCLICK
- height = 1
- left = 29
- top = 5.5
- width = 6
- text = "^"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "BtnText/BtnFace"
- value = false
- endwith
-
-
- this.OPTIMES = new PUSHBUTTON(this)
- with (this.OPTIMES)
- onClick = class::OPCLICK
- height = 1
- left = 22
- top = 5.5
- width = 6
- text = "X"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "darkgreen/BtnFace"
- value = false
- endwith
-
-
- this.OPDIV = new PUSHBUTTON(this)
- with (this.OPDIV)
- onClick = class::OPCLICK
- height = 1
- left = 22
- top = 4
- width = 6
- text = "/"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "darkgreen/BtnFace"
- value = false
- endwith
-
-
- this.OPMINUS = new PUSHBUTTON(this)
- with (this.OPMINUS)
- onClick = class::OPCLICK
- height = 1
- left = 22
- top = 7
- width = 6
- text = "-"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "darkgreen/BtnFace"
- value = false
- endwith
-
-
- this.BUTTONCLEAR = new PUSHBUTTON(this)
- with (this.BUTTONCLEAR)
- onClick = class::BUTTONCLEAR_ONCLICK
- height = 1
- left = 29
- top = 4
- width = 6
- text = "CE\C"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "WHITE/RED"
- value = false
- endwith
-
-
- this.OPEQUAL = new PUSHBUTTON(this)
- with (this.OPEQUAL)
- onClick = class::OPCLICK
- height = 1
- left = 15
- top = 8.5
- width = 6
- text = "="
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "Darkgreen/BtnFace"
- value = false
- endwith
-
-
- this.OPPLUS = new PUSHBUTTON(this)
- with (this.OPPLUS)
- onClick = class::OPCLICK
- height = 1
- left = 22
- top = 8.5
- width = 6
- text = "+"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "darkgreen/BtnFace"
- value = false
- endwith
-
-
- this.MADD = new PUSHBUTTON(this)
- with (this.MADD)
- onClick = class::MEM_ONCLICK
- height = 1
- left = 36
- top = 4
- width = 6
- text = "M+"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "WHITE/BLUE"
- value = false
- endwith
-
-
- this.MSUB = new PUSHBUTTON(this)
- with (this.MSUB)
- onClick = class::MEM_ONCLICK
- height = 1
- left = 36
- top = 5.5
- width = 6
- text = "M-"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "WHITE/BLUE"
- value = false
- endwith
-
-
- this.MR = new PUSHBUTTON(this)
- with (this.MR)
- onClick = class::MR_ONCLICK
- height = 1
- left = 36
- top = 7
- width = 6
- text = "MR"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "WHITE/BLUE"
- value = false
- endwith
-
-
- this.MC = new PUSHBUTTON(this)
- with (this.MC)
- onClick = class::MC_ONCLICK
- height = 1
- left = 36
- top = 8.5
- width = 6
- text = "MC"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "WHITE/BLUE"
- value = false
- endwith
-
-
- this.B_A = new PUSHBUTTON(this)
- with (this.B_A)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 1
- top = 10
- width = 6
- text = "A"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "Blue/BtnFace"
- value = false
- endwith
-
-
- this.B_B = new PUSHBUTTON(this)
- with (this.B_B)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 8
- top = 10
- width = 6
- text = "B"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "Blue/BtnFace"
- value = false
- endwith
-
-
- this.B_C = new PUSHBUTTON(this)
- with (this.B_C)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 15
- top = 10
- width = 6
- text = "C"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "Blue/BtnFace"
- value = false
- endwith
-
-
- this.B_D = new PUSHBUTTON(this)
- with (this.B_D)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 22
- top = 10
- width = 6
- text = "D"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "Blue/BtnFace"
- value = false
- endwith
-
-
- this.B_E = new PUSHBUTTON(this)
- with (this.B_E)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 29
- top = 10
- width = 6
- text = "E"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "Blue/BtnFace"
- value = false
- endwith
-
-
- this.B_F = new PUSHBUTTON(this)
- with (this.B_F)
- onClick = class::DIGIT_ONCLICK
- height = 1
- left = 36
- top = 10
- width = 6
- text = "F"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "Blue/BtnFace"
- value = false
- endwith
-
-
- this.DISPLAY = new TEXT(this)
- with (this.DISPLAY)
- height = 1.6818
- left = 6
- top = 0.3182
- width = 35
- border = true
- metric = 0 // Chars
- colorNormal = "WHITE/BLACK"
- marginHorizontal = 0.1905
- alignVertical = 1 // Middle
- alignHorizontal = 2 // Right
- fontName = "Fixedsys"
- fontSize = 9
- text = "TEXT1"
- borderStyle = 5 // Double
- endwith
-
-
- this.RADIOHEX = new RADIOBUTTON(this)
- with (this.RADIOHEX)
- onGotFocus = {; this.form.KEYHANDLER.setFocus()}
- onChange = class::RADIOHEX_ONCHANGE
- height = 0.8
- left = 3
- top = 2.6
- width = 7
- text = "Hex"
- metric = 0 // Chars
- colorNormal = "WindowText/BtnFace"
- fontSize = 8
- tabStop = false
- group = true
- value = false
- endwith
-
-
- this.RADIODEC = new RADIOBUTTON(this)
- with (this.RADIODEC)
- onGotFocus = {; this.form.KEYHANDLER.setFocus()}
- onChange = class::RADIODEC_ONCHANGE
- height = 0.8
- left = 14
- top = 2.6
- width = 7
- text = "Dec"
- metric = 0 // Chars
- colorNormal = "WindowText/BtnFace"
- fontSize = 8
- tabStop = false
- group = false
- value = true
- endwith
-
-
- this.RADIOOCT = new RADIOBUTTON(this)
- with (this.RADIOOCT)
- onGotFocus = {; this.form.KEYHANDLER.setFocus()}
- onChange = class::RADIOOCT_ONCHANGE
- height = 0.8
- left = 24
- top = 2.6
- width = 7
- text = "Oct"
- metric = 0 // Chars
- colorNormal = "WindowText/BtnFace"
- fontSize = 8
- tabStop = false
- group = false
- value = false
- endwith
-
-
- this.RADIOBIN = new RADIOBUTTON(this)
- with (this.RADIOBIN)
- onGotFocus = {; this.form.KEYHANDLER.setFocus()}
- onChange = class::RADIOBIN_ONCHANGE
- height = 0.8
- left = 34
- top = 2.6
- width = 7
- text = "Bin"
- metric = 0 // Chars
- colorNormal = "WindowText/BtnFace"
- fontSize = 8
- tabStop = false
- group = false
- value = false
- endwith
-
-
- this.OPSQRT = new PUSHBUTTON(this)
- with (this.OPSQRT)
- onClick = class::OPSQRT_ONCLICK
- height = 1
- left = 29
- top = 8.5
- width = 6
- text = "sqrt"
- metric = 0 // Chars
- speedBar = true
- fontSize = 8
- group = true
- colorNormal = "BtnText/BtnFace"
- value = false
- endwith
-
-
- this.TEXTMINDICATOR = new TEXT(this)
- with (this.TEXTMINDICATOR)
- height = 1.7
- left = 2
- top = 0.3
- width = 4
- metric = 0 // Chars
- colorNormal = "BtnText"
- alignVertical = 1 // Middle
- text = " "
- endwith
-
-
- function changeBase( newBase )
- //
- // Change base number system
- //
- local value, memValue, dispFraction, memFraction
-
- // Get values in display and memory before changing
- // hex indicator
- value = CLASS::numVal( this.form.display.text )
- memValue = CLASS::numVal( this.form.memory.value )
- this.form.beforePeriod = true
- SET DECIMALS TO this.form.decPlaces
-
- dispFraction = val(substr( this.form.display.text,;
- at(this.form.periodChar, this.form.display.text)))
- memFraction = val(substr(form.memory.value,;
- at(this.form.periodChar, this.form.memory.value)))
-
- this.form.numberSys := newBase
-
- if ( abs(value) >= HEX_OVERFLOW )
- // Temporary
- this.form.display.text := space(DISPLAY_LEN - MAX_DIGITS_HEX) +;
- replicate("*", MAX_DIGITS_HEX)
- else
- this.form.display.text := CLASS::charVal( value + dispFraction )
- endif
-
- if ( abs(memValue) >= HEX_OVERFLOW )
- this.form.memory.value := space(DISPLAY_LEN - MAX_DIGITS_HEX) +;
- replicate("*", MAX_DIGITS_HEX)
- else
- this.form.memory.value := CLASS::charVal( memValue + memFraction )
- endif
-
- return ( this.form.numberSys )
-
-
- // {Linked Method} form.b0.onClick
- // {Linked Method} form.b3.onClick
- // {Linked Method} form.b2.onClick
- // {Linked Method} form.b1.onClick
- // {Linked Method} form.b6.onClick
- // {Linked Method} form.b5.onClick
- // {Linked Method} form.b4.onClick
- // {Linked Method} form.b9.onClick
- // {Linked Method} form.b8.onClick
- // {Linked Method} form.b7.onClick
- // {Linked Method} form.b_f.onClick
- // {Linked Method} form.b_e.onClick
- // {Linked Method} form.b_d.onClick
- // {Linked Method} form.b_c.onClick
- // {Linked Method} form.b_b.onClick
- // {Linked Method} form.b_a.onClick
- function digit_onClick
- return ( class::enterDigit( this.text ) )
-
- // {Linked Method} form.opplusminus.onClick
- function OPPLUSMINUS_onClick
- //
- // Toggle sign of number in display.
- //
-
- local num
-
- num = class::NumVal( this.form.display.text )
- with ( this.form )
- display.text := class::charVal(num * -1)
- lastKeyOperator := false
- endwith
- return ( this.form.display.text )
-
- // {Linked Method} form.opsqrt.onClick
- function OPSQRT_onClick
- //
- // Replace current diplay with square root of display.
- //
-
- local num, sText
- num = class::NumVal( this.form.display.text )
- if ( num < 0 )
- this.form.display.text := REPLICATE( "*", MAX_DIGITS_DEC )
- else
- this.form.display.text := class::CharVal( SQRT( num ) )
- endif
- this.form.lastKeyOperator := false
- return ( this.form.display.text )
-
- function enterDigit( sDigit )
- //
- // Process a digit.
- //
- local num
-
- if ( this.form.lastKeyOperator )
- with ( this.form )
- lastKeyOperator := false
- beforePeriod := true
- display.text := space(MAX_DIGITS_DEC - 1) +;
- class::displayValue( sDigit )
- endwith
- else
-
- do case
- case class::displayFull()
- ?? chr(7)
- case this.form.beforePeriod
- // Only want rightmost DISPLAY_LEN characters
- this.form.display.text := ;
- right( class::displayValue( this.form.display.text ) + ;
- class::displayValue( sDigit ), ;
- DISPLAY_LEN )
- otherwise
- this.form.display.text := ;
- class::addAfterPeriod( class::displayValue( sDigit ) )
- endcase
-
- endif
-
- return ( this.form.display.text )
-
- // {Linked Method} form.opequal.onClick
- // {Linked Method} form.optimes.onClick
- // {Linked Method} form.oppower.onClick
- // {Linked Method} form.opplus.onClick
- // {Linked Method} form.opminus.onClick
- // {Linked Method} form.opdiv.onClick
- function opClick
- return ( class::enterOp( this ) )
-
- // {Linked Method} form.period.onClick
- function PERIOD_onClick
- //
- // Process decimal point.
- //
-
- if ( this.form.beforePeriod )
- with ( this.form )
- beforePeriod := false
- decPlaces := 1
- endwith
- set decimals to 1
- if ( this.form.lastKeyOperator )
- with ( this.form )
- lastKeyOperator := false
- display.text := ;
- space(MAX_DIGITS_DEC - 1) + this.form.periodChar
- endwith
- else
- this.form.display.text := ;
- class::AddAfterPeriod( this.form.periodChar )
- endif
- endif
-
- return ( this.form.display.text )
-
- function enterOp( thisOp )
- //
- // Process operator.
- //
- local lastOperation, lastOp, lastValue, tempOpList
- if ( this.form.LastKeyOperator or ;
- this.form.operationStack.isEmpty() )
- this.form.lastValue := class::numVal( this.form.display.text )
- else
- // Process all previous operations with >= precedence
- do while ( this.form.operationStack.prevPrecedenceGreaterOrEqual( ;
- thisOp.precedence ) )
- lastOperation = this.form.operationStack.pop()
-
- if ( lastOperation.getPrecedence() > 0 ) // Don't process "="
- lastOp = lastOperation.getOp()
- lastValue = lastOperation.getValue()
- set decimals to this.form.mostDecPlaces
- this.form.lastValue := ;
- lastOp( lastValue, class::numVal( this.form.display.text ) )
- this.form.display.text := class::charVal( this.form.lastValue )
- this.form.decPlaces := 1
- set decimals to 1
- endif
- enddo
- endif
- with ( this.form )
- beforePeriod := true
- lastKeyOperator := true
- endwith
-
- thisOp.opValue = class::numVal( this.form.display.text )
- this.form.operationStack.push( ( thisOp ) )
-
- return ( thisOp.opValue )
-
- // {Linked Method} form.msub.onClick
- // {Linked Method} form.madd.onClick
- function mem_onClick
- //
- // Process a memory action button.
- //
-
- local result
-
- result = this.doIt( class::numVal( this.form.memory.value ),;
- class::numVal( this.form.display.text ))
- with ( this.form )
- memory.value := class::CharVal(result)
- textMindicator.text := "M"
- endwith
- return ( result )
-
- // {Linked Method} form.radiobin.onChange
- function RADIOBIN_onChange
-
- with ( this.form )
- b2.enabled := ( not this.value )
- b3.enabled := ( not this.value )
- b4.enabled := ( not this.value )
- b5.enabled := ( not this.value )
- b6.enabled := ( not this.value )
- b7.enabled := ( not this.value )
- b8.enabled := ( not this.value )
- b9.enabled := ( not this.value )
- endwith
-
- if ( this.value )
- class::changeBase( BASE_BIN )
- endif
-
- return ( this.value )
-
- // {Linked Method} form.radiodec.onChange
- function RADIODEC_onChange
- // Enable keys applicable to decimal calculations
- with ( this.form )
- opPlusMinus.enabled := ( this.value )
- period.enabled := ( this.value )
- endwith
-
- if ( this.value )
- class::changeBase( BASE_DEC )
- endif
-
- return ( this.value )
-
- // {Linked Method} form.radiohex.onChange
- function RADIOHEX_onChange
-
- if ( this.value )
- this.form.height := 11.5
- class::changeBase( BASE_HEX )
- else
- this.form.height := 10
- endif
- return ( this.value )
-
- // {Linked Method} form.radiooct.onChange
- function RADIOOCT_onChange
-
- with ( this.form )
- b8.enabled := ( not this.value )
- b9.enabled := ( not this.value )
- endwith
-
- if ( this.value )
- class::changeBase( BASE_OCT )
- endif
-
- return ( this.value )
-
- function displayFull
- //
- // Check if display already has MAX_DIGITS_DEC digits in it
- //
-
- local bFull, maxValueLen
- bFull = false
- maxValueLen = MAX_DIGITS_DEC
- do case
- case ( this.form.numberSys == BASE_HEX )
- maxValueLen := MAX_DIGITS_HEX
- case ( this.form.numberSys == BASE_OCT )
- maxValueLen := MAX_DIGITS_OCT
- otherwise
- maxValueLen := MAX_DIGITS_DEC
- endcase
-
- // Check if leftmost digit in current display = " "
- bFull := ( not empty( left( right( this.form.display.text, ;
- maxValueLen ), 1) ) )
-
- return ( bFull )
-
- function addAfterPeriod(char)
- //
- // Add fractional digits after decimal point.
- //
- this.form.decPlaces := this.form.decPlaces + 1
- set decimals to this.form.decPlaces
- this.form.mostDecPlaces := max( this.form.decPlaces, ;
- this.form.mostDecPlaces )
-
- return ( class::DisplayValue( this.form.display.text ) + char )
-
- // {Linked Method} form.buttonclear.onClick
- function BUTTONCLEAR_onClick
- //
- // Set custom form properties to default values
- // and clear display..
- //
- this.form.operationStack.Initialize() // Empty operation stack
- set decimals to 1 // Initial decimal places
- with ( this.form )
- lastValue := 0 // Clear value
- lastKeyOperator := null // Clear operators
- decPlaces := 1
- mostDecPlaces := 1
- beforePeriod := true // Start with whole number entry
- display.text := SPACE( MAX_DIGITS_DEC - 1 ) + "0"
- endwith
- return ( this.form.display.text )
-
- function displayValue( value )
- //
- // Display value without the pick character.
- //
- local num, pickLoc
- num = value
- pickLoc = at("&",num)
-
- do case
- case ( pickLoc <> 0 )
- num := stuff(num,pickLoc,1,"")
- case ( right(num,2) = " 0" )
- num := space(MAX_DIGITS_DEC)
- case ( left(num,1) = SPACE(1) )
- num := substr(num,2)
- endcase
-
- return ( num )
-
- // {Linked Method} form.onClose
- function Form_onClose
- //
- // Clean up
- //
- CLOSE PROCEDURE PROGRAM(1)
- return ( true )
-
- // {Linked Method} form.onGotFocus
- function Form_onGotFocus
- //
- // Make sure decimal places is correct every time
- // this form gets focus.
- //
- set decimals to this.decPlaces
- return ( SET("DECIMALS") )
-
- // {Linked Method} form.keyhandler.onChar
- function KEYHANDLER_onChar(nChar, nRepCnt, nFlags)
- local sChar, vChar
- sChar = UPPER( CHR( nChar ) )
- vChar = VAL( sChar )
- if ( vChar > 0 AND vChar < this.form.numberSys )
- class::enterDigit( sChar )
- else
- do case
- case ( sChar == "0" )
- class::enterDigit( sChar )
- case ( sChar == "/" )
- class::enterOp( this.form.opDiv )
- case ( sChar == "*" OR sChar == "X" )
- class::enterOp( this.form.opTimes )
- case ( sChar == "-" )
- class::enterOp( this.form.opMinus )
- case ( sChar == "+" )
- class::enterOp( this.form.opPlus )
- case ( sChar == "^" )
- class::enterOp( this.form.opPower )
- case ( sChar == "=" OR nChar == 13 )
- class::enterOp( this.form.opEqual )
- case ( sChar == "." and this.form.period.enabled )
- class::period_OnClick()
- endcase
- endif
- return (nChar)
-
- // {Linked Method} form.mc.onClick
- function MC_onClick
- //
- // Memory Clear
- //
- local thisForm
- if ( TYPE("this.form") == "O" )
- thisForm = this.form
- else
- thisForm = this
- endif
- with ( thisForm )
- lastKeyOperator := true
- memory.value := space(MAX_DIGITS_DEC - 1) + "0"
- textMIndicator.text := null
- endwith
- return ( thisForm.memory.value )
-
- // {Linked Method} form.mr.onClick
- function MR_onClick
- //
- // Recall from memory.
- //
-
- if ( this.form.lastKeyOperator )
- with ( this.form )
- lastKeyOperator := false
- beforePeriod := true
- endwith
- endif
- this.form.lastValue := class::numVal( this.form.display.text )
- this.form.display.text := this.form.memory.value
- return ( this.form.display.text )
-
- // {Linked Method} form.open
- function Form_open
- set procedure to program(1) additive
- set decimals to 1
- this.height := 10 // hide hex
-
- this.periodChar = setto("point") // Set point type for
- this.period.text := this.periodChar // current country
-
- this.opPlus.doIt = { |a,b| ; return ( a + b ) }
- this.opPlus.precedence = 1
-
- this.opMinus.doIt = { |a,b| ; return ( a - b ) }
- this.opMinus.precedence = 1
-
- this.opTimes.doIt = { |a,b| ; return ( a * b ) }
- this.opTimes.precedence = 2
-
- this.opDiv.doIt = class::OpDivideIt
- this.opDiv.precedence = 2
-
- this.opPower.doIt = { |a,b| ; return ( a ^ b ) }
- this.opPower.precedence = 3
-
- this.opEqual.doIt = { |a,b| ; return null }
- this.opEqual.precedence = 0
-
- this.mAdd.doIt = { |a,b| ; return ( a + b ) }
- this.mAdd.precedence = 1
-
- this.mSub.doIt = { |a,b| ; return ( a - b ) }
- this.mSub.precedence = 1
-
- //
- // Create custom form properties
- //
- // Stack for storing operation states
- this.operationStack = new OperationStackClass()
- this.operationStack.Initialize() // Empty operation stack
-
- this.numberSys = BASE_DEC
- this.decPlaces = 1 // Start with minimum decimal places
- this.mostDecPlaces = 1 // Most decimal places in an operand
-
- this.beforePeriod = true // Add numbers before or after decimal pt.
- this.lastKeyOperator = null
- this.lastValue = 0
- this.display.text := SPACE( MAX_DIGITS_DEC - 1 ) + "0"
- class::MC_onClick()
-
- this.KEYHANDLER.setFocus()
- return ( CALCULATORFORM::OPEN() )
-
- function opDivideIt( a, b )
- local nResult
- nResult = 0
- if ( b == 0 )
- MSGBOX("Cannot divide by zero.","Alert",48)
- else
- nResult := ( a / b )
- endif
- return ( nResult )
-
- function charVal( num )
- //
- // Convert decimal number to string using
- // current base: hex, decimal, octal, binary.
- //
- local string, fractionVal
- local nPlace
- local nPValue
- string = ""
-
- do case
- case ( this.form.numberSys == BASE_HEX )
-
- if ( ABS(num) >= HEX_OVERFLOW )
- string := replicate("*", MAX_DIGITS_HEX)
- else
- string := itoh(num)
- string := space(MAX_DIGITS_DEC - len(string)) + string
- endif
-
- case ( this.form.numberSys == BASE_OCT )
- string := class::toBaseString( num, 16, BASE_OCT )
-
- case ( this.form.numberSys == BASE_BIN )
- string := class::toBaseString( num, 16, BASE_BIN )
-
- case ( this.form.numberSys == BASE_DEC )
- if ( ABS(num) >= DEC_OVERFLOW )
- string := replicate("*", MAX_DIGITS_DEC)
- else
- string := str(num, MAX_DIGITS_DEC, this.form.decPlaces)
- if ( VAL(right(string, this.form.decPlaces)) == 0 ) // If fraction = 0
- string := str(num, MAX_DIGITS_DEC)
- endif
- endif
-
- endcase
- return ( string )
-
- function toBaseString( nDecValue, nMaxPlace, nBase )
- local nPlace
- local npValue
- local nAdd
- local sValue
- local bStart
- local bCarry
-
- nPlace = nMaxPlace
- npValue = 0
- sValue = ""
- bStart = false
- if ( ABS( nDecValue ) >= nBase ^ nPlace )
- sValue = REPLICATE("*", nMaxPlace )
- else
- do while ( nPlace >= 0 )
- if ( nDecValue == 0 )
- sValue := sValue + "0"
- else
- npValue := ( nBase ^ nPlace )
- if ( ( npValue <= nDecValue ) or ;
- ( npValue == 1 ) )
- bStart := true
- if ( nDecValue / npValue ) == nBase
- sValue := sValue + "10"
- else
- sValue := sValue + ;
- ALLTRIM( STR( INT( nDecValue / npValue ) ) )
- endif
- nDecValue := MOD( nDecValue, npValue )
- else
- if ( bStart )
- sValue := sValue + "0"
- endif
- endif
- endif
- nPlace := nPlace - 1
- enddo
- if ( VAL( sValue ) == 0 )
- sValue := "0"
- endif
- sValue := SPACE( MAX_DIGITS_DEC - LEN( sValue ) ) + sValue
- endif
- return ( sValue )
-
- function numVal( string )
- //
- // Return decimal value of display value using
- // current base to translate.
- //
- local h, num, nPeriod
- local sValue
- local nDigit, nPlace
- private macro
-
- sValue = ALLTRIM( string )
- h = ""
- macro = ""
- num = 0
- nDigit = 0
- nPlace = 0
- nPeriod = 0
-
- do case
-
- case ( this.form.numberSys == BASE_HEX )
-
- h := htoi(string)
- num := iif(h >= HEX_OVERFLOW/2, bitxor(h, HEX_OVERFLOW), h)
-
- case ( this.form.numberSys == BASE_OCT )
-
- if ( sValue == null )
- num := 0
- else
- if ( SUBSTR( sValue, 1, 1 ) == "*" )
- num := ( 1 / 0 )
- else
- macro := "0" + sValue
- num := ¯o.
- endif
- endif
-
- case ( this.form.numberSys == BASE_BIN )
-
- do while ( LEN( sValue ) > 0 )
- nDigit := IIF( RIGHT( sValue, 1 ) == "1", 1, 0 )
- sValue := SUBSTR( sValue, 1, ( LEN( sValue ) - 1 ) )
- num := num + ( nDigit * (2 ^ nPlace) )
- nPlace := nPlace + 1
- enddo
-
- otherwise
-
- // decimal
- nPeriod := AT( this.form.periodChar, sValue )
-
- if ( nPeriod <> 0 )
- num := VAL( STUFF( sValue, nPeriod, 1, "." ) )
- else
- num := VAL( sValue )
- endif
-
- endcase
-
- return ( num )
- endclass
- class OperationStackClass
- //
- // This class defines a stack object for storing
- // mathematical operation states. This is necessary
- // for using operators that have different precedence, like
- // + and *. This is a stack of OperationStateClass objects.
- //
-
- class::initialize()
-
-
- function initialize
- //
- // Create empty stack
- //
-
- // Bottom (and top, at first) of Stack
- this.stackTop = new OperationStateClass()
- return true
-
- function isEmpty
- //
- // Check if stack is empty
- //
-
- return empty( this.stackTop.getNext() ) // Empty if no more operations
-
-
- function pop
- //
- // Retrieve last operation state
- //
- local xOp
- xOp = false
-
- if ( empty(this.stackTop.getNext()) )
- InformationMessage("ERROR: Trying to pop empty stack", "Info")
- else
- xOp := this.stackTop
- this.stackTop = this.stackTop.getNext()
- endif
-
- return xOp
-
-
- function push( operation )
- //
- // Save last operation state
- //
- local newStackTop
-
- newStackTop = new operationStateClass() // Create new operationState
- newStackTop.assign( operation ) // Assign to it properties of
- // operation
- newStackTop.setNext( this.stackTop ) // Make current top be next
-
- this.stackTop = newStackTop // Make new operation be top
-
- return true
-
-
- function prevPrecedenceGreaterOrEqual(curPrecedence)
- //
- // Retrieve last operation state
- //
- return ( this.stackTop.getPrecedence() >= curPrecedence )
-
- endclass
-
-
- class OperationStateClass
- //
- // This class defines a single operation state, which is to
- // be stored on the operationStack
- //
-
- this.op = { |a,b| ; return null }
- this.precedence = -1
- this.opValue = 0
- this.next = false
-
- function getOp
- return ( this.op )
-
-
- function setOp( newOp )
- this.op := newOp
- return ( this.op )
-
-
- function getPrecedence
- return ( this.precedence )
-
-
- function setPrecedence( newPrecedence )
- this.precedence := newPrecedence
- return ( this.precedence )
-
-
- function getValue
- return ( this.opValue )
-
- function setValue( newValue )
- this.opValue := newValue
- return ( this.opValue )
-
-
- function getNext
- return ( this.next )
-
- function setNext(newNext)
- this.next := newNext
- return ( this.next )
-
- function assign( newOperationState )
- with ( this )
- op := newOperationState.doIt
- precedence := newOperationState.precedence
- opValue := newOperationState.opValue
- endwith
- return ( this.opValue )
-
- endclass
-